﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Threading;

namespace _4591BRD
{
    class BRDWork
    {
        private static BRDWork _instance = null;
        public static BRDWork Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new BRDWork();
                return _instance;
            }
        }

        private int _updateInterval = 60000; //60秒

        private DateTime CurrentDate; //当前处理的日期
        private DateTime NextDate;  //下一个处理的日期

        private DateTime earliestDate;
        private DateTime lastestDate;

        private int maxThreadNum = 2;

        string path;

        public BRDWork()
        {
            doStop = false;

            path = Common.BRDLogPath;

            //线程
            int.TryParse(ConfigurationSettings.AppSettings["MaxThreadNum"].ToString(), out maxThreadNum);

            CurrentDate = DateTime.Now;
            NextDate = CurrentDate;

            earliestDate = DateTime.Now;
            lastestDate = earliestDate;
        }

        private bool doStop;

        public void Close()
        {
            doStop = true;
        }

        private DateTime lastMakeMonthlyRankTime;
        private DateTime lastMakeDaillyRankTime;
        private DateTime lastMakeAllRankTime;

        public void Run()
        {
            lastMakeMonthlyRankTime = DateTime.Now.AddDays(-1);
            lastMakeDaillyRankTime = DateTime.Now.AddDays(-1);
            lastMakeAllRankTime = DateTime.Now.AddDays(-1);

            if (Directory.Exists(path))
            {
                while (!doStop)
                {
                    //循环等待时间
                    int iTickTime = _updateInterval;
                                        
                    //遍历所有文件，设置下一个处理的日期
                    int iCurCount = CheckFiles();
                    NextDate = earliestDate;
                    
                    if (iCurCount > 0)
                    {
                        //如果上一次执行的日期和将要处理的日期不一样，清除天缓存
                        if (CurrentDate != NextDate)  
                        {
                            //清除天缓存数据
                            CurrentDateManager.Instance.ClearCharDataDaily();

                            //如果月份不一样，清除月缓存
                            if (CurrentDate.Month != NextDate.Month)
                            {
                                //清除月缓存数据
                                CurrentDateManager.Instance.ClearCharDataMonthly();
                            }
                        }

                        CurrentDate = NextDate;

                        //读取并处理文件
                        ReadBRDFiles();

                        //再次遍历文件
                        int iNextCount = CheckFiles();
                        NextDate = earliestDate;

                        int timeX = CurrentDate.CompareTo(earliestDate);
                        if (timeX < 0) //有下一天的文件
                        {
                            iTickTime = 1;

                            //保存今天数据
                            CurrentDateManager.Instance.SaveCharData(0);

                            //制作天排名数据
                            new MakeRankData(0, CurrentDate).MakeDailyRank();

                            //下一个文件也是本月
                            if (CurrentDate.Month == NextDate.Month)
                            {
                                //生成角色数据文件
                                if (!Common.OnlyMakeRank)
                                    MakeCharDataFilesDaily();
                            }
                            else //下一个文件是下个月了
                            {
                                //保存本月数据
                                CurrentDateManager.Instance.SaveCharData(1);

                                //制作月排名数据
                                new MakeRankData(0, CurrentDate).MakeMonthlyRank();

                                //生成角色数据文件
                                if (!Common.OnlyMakeRank)
                                    MakeCharDataFilesMonthly();
                            }
                        }
                        else if (timeX == 0) //是最后一天的文件
                        {
                            if (iNextCount > 0) //又来新文件了，说明是当天
                            {
                                //立即处理下一次
                                iTickTime = 1;
                            }
                            else //无新文件，下次等待较长时间
                            {
                                //保存今天数据
                                CurrentDateManager.Instance.SaveCharData(0);

                                if ((DateTime.Now - lastMakeDaillyRankTime).TotalMinutes > 30)
                                {
                                    //制作天排名数据
                                    new MakeRankData(0, CurrentDate).MakeDailyRank();

                                    lastMakeDaillyRankTime = DateTime.Now;
                                }

                                //保存本月数据
                                CurrentDateManager.Instance.SaveCharData(1);

                                if ((DateTime.Now - lastMakeMonthlyRankTime).TotalMinutes > 60)
                                {
                                    //制作月排名数据
                                   // new MakeRankData(0, CurrentDate).MakeMonthlyRank();

                                    lastMakeMonthlyRankTime = DateTime.Now;
                                }

                                CurrentDateManager.Instance.SaveCharData(2);

                                //生成角色数据文件
                                if (!Common.OnlyMakeRank)
                                    MakeCharDataFilesMonthly();
                            }
                        }
                    }
                    else //无文件可处理
                    {
                        Log.WriteLine(1, "No Files, Wait for........" + iTickTime.ToString());
                    }

                    //等待下一次执行
                    Thread.Sleep(iTickTime);
                }
            }
        }

        //遍历所有文件
        private int CheckFiles()
        {
            //刚启动时，先遍历所有文件，将“当前时间”设为最早的日期
            int iCountFiles = 0;
            string[] files = Directory.GetFiles(path, "*.brd");
            foreach (string file in files)
            {
                string[] sKeys = file.Split(' ');
                if (sKeys.Length > 1)
                {
                    string dateString = sKeys[1];
                    DateTime tmpDate = DateTime.Parse(dateString);

                    if (iCountFiles == 0)
                    {
                        earliestDate = tmpDate;
                        lastestDate = tmpDate;
                    }
                    else
                    {
                        //最早时间 大于 文件日期
                        if (earliestDate.CompareTo(tmpDate) > 0)
                        {
                            earliestDate = tmpDate;
                        }

                        //最晚时间 小于 文件时间
                        if (lastestDate.CompareTo(tmpDate) < 0)
                        {
                            lastestDate = tmpDate;
                        }
                    }
                    iCountFiles++;
                }
            }

            return iCountFiles;
        }

        private bool IsLastestDate()
        {
            if (CurrentDate == lastestDate)
                return true;
            else
                return false;
        }

        private void ReadBRDFiles()
        {
            DateTime startTime = DateTime.Now;

            string dateStr = CurrentDate.Year.ToString() + "-" + CurrentDate.Month.ToString() + "-" + CurrentDate.Day.ToString();
            Log.WriteLine(1, "Start Reading BRD Files..." + dateStr);

            //读取所有“当前日期”的文件
            string[] files = Directory.GetFiles(path, "* " + dateStr + " *.brd");
            int iFileCount = files.Length;

            //设置本次运行的“文件日期”
            CurrentDateManager.Instance.SetCurrentDate(dateStr);

            //创建相关表格
            //Common.CheckDataTables(CurrentDate);

            int iCount = 0;
            if (iFileCount > 0)
            {
                //读文件数据
                foreach (string file in files)
                {
                    iCount = 1;
                    while (Common.GetThreadCount() >= maxThreadNum)
                    {
                        if (iCount % 10 == 0)
                            Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                        Thread.Sleep(1000);
                        iCount++;
                    }

                    DataFileReader rwt = new DataFileReader(file, dateStr);
                    //ThreadPool.QueueUserWorkItem(new WaitCallback(rwt.Run));

                    Thread workerThread = new Thread(rwt.Run);
                    workerThread.Priority = ThreadPriority.BelowNormal;
                    workerThread.Start();
                }
            }

            iCount = 0;
            Thread.Sleep(1000);
            //等待所有线程结束
            while (Common.GetThreadCount() > 0)
            {
                if (iCount % 10 == 0)
                    Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                iCount++;
                Thread.Sleep(1000);
            }

            bool allFileMoved = false;
            while (!allFileMoved)
            {
                try
                {
                    Thread.Sleep(1000);
                    //处理结束后，将所有文件移至备份文件夹BackupBRDPath
                    foreach (string file in files)
                    {
                        if (File.Exists(file))
                        {
                            string destPath = ConfigurationSettings.AppSettings["BackupBRDPath"].ToString();// +dateStr;
                            string filename = file.Substring(file.LastIndexOf("\\") + 1);
                            string destFile = destPath + "\\" + filename;
                            if (!Directory.Exists(destPath))
                                Directory.CreateDirectory(destPath);
                            if (File.Exists(destFile))
                                File.Delete(destFile);

                            File.Move(file, destPath + "\\" + filename);
                        }
                    }
                    allFileMoved = true;
                    break;
                }
                catch (IOException e)
                {
                    Log.WriteError("Error On Move!!! " + e.Message);
                }
            }

            DateTime endTime = DateTime.Now;
            Log.WriteLine(1, "Finish Reading " + iFileCount.ToString() + " Files in " + (endTime - startTime).TotalSeconds.ToString() + "s");
        }

        private void MakeCharDataFilesDaily()
        {
            DateTime startTime = DateTime.Now;

            //创建生成角色数据文件的工作线程
            int inum = CurrentDateManager.Instance.CharDataCacheDaily.Count;
            Log.WriteLine(1, "Start Making Char Data..." + CurrentDate.ToShortDateString());

            int iCount = 0;
            int i = 0;
            foreach (KeyValuePair<int, CharDataObj> obj in CurrentDateManager.Instance.CharDataCacheDaily)
            {
                iCount = 1;
                while (Common.GetThreadCount() >= maxThreadNum)
                {
                    if (iCount % 10 == 0)
                        Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                    Thread.Sleep(1000);
                    iCount++;
                }

                MakePersonalData rwt = new MakePersonalData(CurrentDate, obj.Key);
                //ThreadPool.QueueUserWorkItem(new WaitCallback(rwt.Run));

                Thread workerThread = new Thread(rwt.Run);
                workerThread.Priority = ThreadPriority.BelowNormal;
                workerThread.Start();

                i++;
            }

            //生成结束，清除角色数据
            //CurrentDateManager.Instance.ClearCharDataCache();

            iCount = 0;
            Thread.Sleep(1000);
            //等待所有线程结束
            while (Common.GetThreadCount() > 0)
            {
                if (iCount % 10 == 0)
                    Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                iCount++;
                Thread.Sleep(1000);
            }

            DateTime endTime = DateTime.Now;
            Log.WriteLine(1, "Finish Making " + inum.ToString() + " CharData in " + (endTime - startTime).TotalSeconds.ToString() + "s");
        }

        private void MakeCharDataFilesMonthly()
        {
            DateTime startTime = DateTime.Now;

            //创建生成角色数据文件的工作线程
            int inum = CurrentDateManager.Instance.CharDataCacheDaily.Count;
            Log.WriteLine(1, "Start Making Char Data..." + CurrentDate.ToShortDateString());

            int iCount = 0;
            int i = 0;
            foreach (KeyValuePair<int, CharDataObj> obj in CurrentDateManager.Instance.CharDataCacheMonthly)
            {
                iCount = 1;
                while (Common.GetThreadCount() >= maxThreadNum)
                {
                    if (iCount % 10 == 0)
                        Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                    Thread.Sleep(1000);
                    iCount++;
                }

                MakePersonalData rwt = new MakePersonalData(CurrentDate, obj.Key);
                //ThreadPool.QueueUserWorkItem(new WaitCallback(rwt.Run));

                Thread workerThread = new Thread(rwt.Run);
                workerThread.Priority = ThreadPriority.BelowNormal;
                workerThread.Start();

                i++;
            }

            //生成结束，清除角色数据
            //CurrentDateManager.Instance.ClearCharDataCache();

            iCount = 0;
            Thread.Sleep(1000);
            //等待所有线程结束
            while (Common.GetThreadCount() > 0)
            {
                if (iCount % 10 == 0)
                    Log.WriteLine(1, "Working Threads = " + Common.GetThreadCount().ToString());
                iCount++;
                Thread.Sleep(1000);
            }

            DateTime endTime = DateTime.Now;
            Log.WriteLine(1, "Finish Making " + inum.ToString() + " CharData in " + (endTime - startTime).TotalSeconds.ToString() + "s");
        }
    }
}
